﻿using UnityEngine;
using System.Collections;
using FrenzyIsland.UI;


[RequireComponent(typeof(Camera))]
public class CameraRigAction : MonoBehaviour {

    public float radius = 2.0f;
    public uint movementVelocity = 1;
    public uint maxOrthographicSize = 20;
    public float zoomFactor = 0.1f;
    public int rotationDurationMilliseconds = 1000;

    public GameObject anchor;
    
    private float _padScroll;
    private bool _isRotating = false;
    private bool isResponsive = true;
    private float _currentAngle = 0f;
    private float _startAngle = 0f;
    private float _endAngle = 0f;
    private float _currentTime = 0f;

    //touch camara
    Vector2?[] oldTouchPositions = {
		null,
		null
	};

    public bool IsResponsive {
        get {
            return this.isResponsive;
        }

        set {
            this.isResponsive = value;
        }
    }


    private Vector3 center;
	
	void Update () { 
        if (this.isResponsive) { 
		    if (Input.touchCount == 0){
                oldTouchPositions[0] = null;
                oldTouchPositions[1] = null;
            }
        
            //se è cominciato un ciclo di rotazione occorre portarlo a termine,
            //viceversa è possibile accogliere nuovi input.
            if (this._isRotating) {
            
                //converto dapprima il tempo di durata dell'animazione in secondi
                //quindi calcolo a che punto siamo dell'animazione
                //e infine incremento l'asse temporale.
                float durationSec = this.rotationDurationMilliseconds/1000f;
                float pivot = Mathf.Clamp01(this._currentTime / durationSec);
                this._currentTime += Time.deltaTime;

                //effettuo l'interpolazione lineare usando il pivot temporale in [0,1]
                //fra l'angolo iniziale e quello finale, caloolo la differenza di
                //gradi fra questa e la precedente rotazione
                float lastAngle = Mathf.Lerp(this._startAngle, this._endAngle, pivot);
                float deltaAngle = this._currentAngle - lastAngle;
                this._currentAngle = lastAngle;
            
                //ruoto di deltaAngle gradi rispetto al centro.
                this.orientCamera(deltaAngle);

                //condizione di uscita: animazione terminata.
                if (pivot == 1) {
                    this._isRotating = false;
                    this._currentTime = 0;
                }

            } 
                //telecamera normale
                if( Input.touchCount == 0 )
                {
                    //legge gli input dal gestore
                    float hAxis = Input.GetAxis("Horizontal");
                    float vAxis = Input.GetAxis("Vertical");
                    float scrollAxis = this.mouseScroll;

                    //verifica se la telecamera deve seguire un oggetto in particolare.
                    if (this.anchor != null)
                    {
                        Vector3 position = this.anchor.transform.position - this.transform.TransformDirection(Vector3.forward * this.radius);
                        this.transform.position = position;
                    }

                    //se in presenza di input per la traslazione della telecamera la esegue
                    //eventualmente disancorandosi da un oggetto da seguire.
                    if (hAxis != 0 || vAxis != 0)
                    {
                        this.anchor = null;

                        Vector3 x = this.transform.TransformDirection(Vector3.right);
                        Vector3 z = Vector3.Cross(x, Vector3.up).normalized;
                        this.transform.localPosition += (x * hAxis + z * vAxis) * this.movementVelocity;
                    }

                    //se non è in corso una rotazione e si è in presenza di input 
                    //per la rotazione oraria e antioraria la esegue.
                    if (!this._isRotating && Input.GetKeyDown(KeyCode.Q) || Input.GetKeyDown(KeyCode.E))
                    {
                        this._isRotating = true;
                        this._startAngle = this._currentAngle;

                        if (Input.GetKeyDown(KeyCode.Q))
                        {
                            this._endAngle = this._startAngle - 90.0f;
                        }
                        else if (Input.GetKeyDown(KeyCode.E))
                        {
                            this._endAngle = this._startAngle + 90.0f;
                        }
                    }

                    //se in presenza di scrolling allora effettua lo zoom.
                    if (scrollAxis != 0)
                    {
                        Camera camera = this.GetComponent<Camera>();
                        if (scrollAxis > 0)
                        {
                            if (camera.orthographicSize - this.zoomFactor > 1)
                            {
                                camera.orthographicSize -= this.zoomFactor;
                                camera.nearClipPlane += this.zoomFactor;
                            }
                        } if (scrollAxis < 0)
                        {
                            if (camera.orthographicSize + this.zoomFactor < this.maxOrthographicSize)
                            {
                                camera.orthographicSize += this.zoomFactor;
                                camera.nearClipPlane -= this.zoomFactor;
                            }
                        }
                    }
                }

                //mi sposto con il ditino
                if( Input.touchCount == 1)
                {
                    if (oldTouchPositions[0] == null || oldTouchPositions[1] != null)
                    {
                        oldTouchPositions[0] = Input.GetTouch(0).position;
                        oldTouchPositions[1] = null;
                    }
                    else
                    {
                        Vector2 newTouchPosition = Input.GetTouch(0).position;
                        transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] - newTouchPosition) * GetComponent<Camera>().orthographicSize / GetComponent<Camera>().pixelHeight * 2f));
                        oldTouchPositions[0] = newTouchPosition;
                    }
                }
            } 
	    
	}

    private void SetZoom(float zoom)
    {
        Camera camera = this.GetComponent<Camera>();
        if (camera.orthographicSize == zoom) return;
        float diff = camera.orthographicSize - zoom;
        camera.orthographicSize -= diff;
        camera.nearClipPlane += this.zoomFactor * diff;
    }

    void OnDrawGizmosSelected() {
        Vector3 center;
        if (this.anchor) {
            center = this.anchor.transform.position;
        } else {
            center = this.transform.position + this.transform.TransformDirection(Vector3.forward * this.radius);
        }
        Vector3 xDirection = this.transform.TransformDirection(Vector3.right);
        Vector3 zDirection = Vector3.Cross(xDirection, Vector3.up);

        Gizmos.DrawRay(center, xDirection * this.radius);
        Gizmos.DrawRay(center, zDirection * this.radius);
        Gizmos.DrawWireSphere(center, this.radius);
        Gizmos.DrawLine(
            this.transform.position,
            this.transform.position + this.transform.TransformVector(Vector3.forward * this.radius)
        );
    }

    
    private void orientCamera(float angle) {
        Vector3 position = this.transform.position;
        Vector3 center;
        if (this.anchor) {
            center = this.anchor.transform.position;
        } else {
            center = this.transform.position + this.transform.TransformDirection(Vector3.forward * this.radius);
        }
        float x = center.x + (this.radius * Mathf.Cos(angle * Mathf.Deg2Rad));
        float y = this.transform.position.y;
        float z = center.z + (this.radius * Mathf.Sin(angle * Mathf.Deg2Rad));

        this.transform.RotateAround(center, Vector3.up, angle);
    }


    public void focusOnObject(GameObject target) {

        //this.anchor = target;

        Vector3 position = target.transform.position - this.transform.TransformDirection(Vector3.forward * this.radius);
        this.transform.position = position;

        SetZoom(3);
    }


    void OnGUI() {
        if (Event.current.type == EventType.ScrollWheel) {
            _padScroll = -Event.current.delta.y / 100;
        } else {
            _padScroll = 0;
        }
    }


    public float mouseScroll {
        get {
            float mouseScroll = Input.GetAxis("Mouse ScrollWheel");

            if (mouseScroll == 0) {
                mouseScroll = this._padScroll;
            }

            return mouseScroll;
        }
    }

}
